#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "hashtable.h"
#include "perfecthashtable.h"
void Help(void);
void TestPHT(void);
void TestHT(void);

/*
*
* Write more tests!
*
* Hash your life! Hash the world!!!
*
*/

//! Defines a single mapping from a string to a function.
typedef struct LCaseMapping
{
	char *String;
	void (*Function)(void);
} CaseMapping;

//! Defines a set of strings mapped to functions.
CaseMapping Mapping[] =
{
	{"help", Help},
	{"pht", TestPHT},
	{"ht", TestHT},
};

/*!
  Tester entry point.
*/
int main(int argc, char *argv[])
{
	int i=0;
	int numMappings = sizeof(Mapping)/sizeof(struct LCaseMapping);
	void (*func)(void) = 0x0;

	if (argc <= 1)
	{
		printf("Enter a test case as an argument.\n\n");
		return 0;
	}
	while (i < numMappings)
	{
		if (strcmp(argv[1], Mapping[i].String) == 0)
			func = Mapping[i].Function;
		i=i+1;
	}
	if (func != 0x0)
		func();
	return 0;
}

// Test Cases Follow:

/*!
  Print the array of mappings.
  This function should be in every tester
*/
void Help(void)
{
	int i=0;
	int numMappings = sizeof(Mapping)/sizeof(struct LCaseMapping);
	printf("Mappings:\n");
	while (i < numMappings)
	{
		printf("  >%s\n", Mapping[i].String);
		i=i+1;
	}
}

void TestPHT(void)
{
	// Initialize function variables
	char key[]="abc";
	char *value = (char*)malloc(strlen("First three letters in the alphabet."));
	char key2[]="def";
	int *value2=(int*)malloc(sizeof(int));
	char *retValue;
	int *retValue2;
	strcpy(value, "First three letters in the alphabet.");
	*value2 = 100;

	// Create perfect hash table (double hashing)
	printf("Creating hashtable\n");
	PerfectHashTable ht = new(PerfectHashTable, 100);
	printf("Setting values\n");
	printf("  %s => %s\n", key, value); // Set abc=>First three letters in the alphabet.
	ht.Set(&ht, key, value);
	printf("  %s => %d\n", (char*)&key2, *value2); // Set def=>100
	ht.Set(&ht, key2, value2);

	printf("Retreiving value\n");
	retValue = (char*)ht.Get(&ht, key);
	printf("H[%s]: %s\n", key, retValue); // Get H[abc]
	retValue2 = (int*)ht.Get(&ht, key2);
	printf("H[%s]: %d\n", key2, *retValue2); // Get H[def]

	destroy(PerfectHashTable, &ht); // Destroy table
}

void TestHT(void)
{
	// Initialize function variables
	char key[]="abc";
	char *value = (char*)malloc(strlen("First three letters in the alphabet."));
	char key2[]="def";
	int *value2=(int*)malloc(sizeof(int));
	char *retValue;
	int *retValue2;
	strcpy(value, "First three letters in the alphabet.");
	*value2 = 100;

	// Create hash table
	printf("Creating hashtable\n");
	HashTable ht = new(HashTable, 100);
	printf("Setting values\n");
	printf("  %s => %s\n", key, value); // set abc=>First three letters in the alphabet.
	ht.Set(&ht, key, value);
	printf("  %s => %d\n", (char*)&key2, *value2); // set def=>100
	ht.Set(&ht, key2, value2);

	printf("Retreiving value\n");
	retValue = (char*)ht.Get(&ht, key); // get H[abc]
	printf("H[%s]: %s\n", key, retValue);
	retValue2 = (int*)ht.Get(&ht, key2); // get H[def]
	printf("H[%s]: %d\n", key2, *retValue2);

	destroy(HashTable, &ht); // Destroy table
}
